home *** CD-ROM | disk | FTP | other *** search
/ Aminet 28 / Aminet 28 (1998)(GTI - Schatztruhe)[!][Dec 1998].iso / Aminet / dev / c / qtools0.2-src.lha / src / libqtools / pak.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-08-12  |  9.7 KB  |  372 lines

  1. #define    LIBQTOOLS_CORE
  2. #include "../include/libqtools.h"
  3.  
  4. /*
  5.  * PAK-tools
  6.  *
  7.  * entryName    == 0  -> OP_EXTRACT all
  8.  * destDir == 0  -> OP_EXTRACT to current directory
  9.  */
  10.  
  11. /*
  12.  *
  13.  */
  14.  
  15. bool CheckPAK(HANDLE pakFile, struct packheader *Header, bool newWad)
  16. {
  17.   if (pakFile) {
  18.     __lseek(pakFile, 0, SEEK_END);
  19.     if (!__ltell(pakFile)) {
  20.       if (newWad) {
  21.     /*
  22.      * file is new 
  23.      */
  24.     Header->magic.integer = BigLong(MAGIC_PACK);
  25.     Header->offset = LittleLong(sizeof(struct packheader));
  26.  
  27.     Header->size = LittleLong(0);
  28.     __write(pakFile, Header, sizeof(struct packheader));
  29.  
  30.     return TRUE;
  31.       }
  32.       else
  33.     return FALSE;
  34.     }
  35.     else {
  36.       __lseek(pakFile, 0, SEEK_SET);
  37.       __read(pakFile, Header, sizeof(struct packheader));
  38.  
  39.       return Header->magic.integer == BigLong(MAGIC_PACK) ? TRUE : FALSE;
  40.     }
  41.   }
  42.   else
  43.     return FALSE;
  44. }
  45.  
  46. /*
  47.  * findpak return ever one entry more than exists!
  48.  */
  49. struct packentry *FindPAK(HANDLE pakFile, char *entryName, struct packheader *Header, struct packentry **Entry)
  50. {
  51.   struct packentry *allEntries;
  52.  
  53.   __lseek(pakFile, LittleLong(Header->offset), SEEK_SET);
  54.   if ((*Entry = allEntries = (struct packentry *)tmalloc(LittleLong(Header->size) + sizeof(struct packentry)))) {
  55.     int i;
  56.  
  57.     __read(pakFile, allEntries, LittleLong(Header->size));
  58.     if (entryName) {
  59.       for (i = 0; i < (LittleLong(Header->size) / sizeof(struct packentry)); i++) {
  60.     if (!fnmatch(entryName, allEntries->name, FNM_PATHNAME)) {
  61.       /*
  62.        * return offset of valid entry 
  63.        */
  64.       return allEntries;
  65.     }
  66.     allEntries++;
  67.       }
  68.     }
  69.     /*
  70.      * not in pakfile 
  71.      */
  72.     return 0;
  73.   }
  74.   else
  75.     return (struct packentry *)-1;
  76. }
  77.  
  78. struct packentry *SearchPAK(char *entryName, struct packheader *Header, struct packentry *allEntries)
  79. {
  80.   int i;
  81.  
  82.   for (i = 0; i < (LittleLong(Header->size) / sizeof(struct packentry)); i++) {
  83.     if (!fnmatch(entryName, allEntries->name, FNM_PATHNAME))
  84.       return allEntries;
  85.     allEntries++;
  86.   }
  87.   return 0;
  88. }
  89.  
  90. bool ExtractPAK(HANDLE pakFile, FILE * script, char *destDir, char *entryName, unsigned char outType, operation procOper, bool recurse)
  91. {
  92.   struct packheader Header;
  93.   struct packentry *Entry, *allEntries;
  94.   bool retval = FALSE;
  95.  
  96.   if (CheckPAK(pakFile, &Header, FALSE)) {
  97.     /*
  98.      * we assume that the dir is at the end of the file!!!!! 
  99.      */
  100.     switch ((long int)(Entry = FindPAK(pakFile, entryName, &Header, &allEntries))) {
  101.       case -1:
  102.     eprintf(failed_memory, LittleLong(Header.size) + sizeof(struct packentry), "packentries");
  103.     break;
  104.       case 0:
  105.     if ((entryName) && (*entryName != '\0')) {
  106.       eprintf("no entry %s found in pak\n", entryName);
  107.       break;
  108.     }
  109.       default:{
  110.       int i, parseCount;
  111.       
  112.       parseCount = (LittleLong(Header.size) / sizeof(struct packentry));
  113.  
  114.       /* process only ONE (case 0:) */
  115.       if (Entry) {
  116.         i = Entry - allEntries;
  117.         parseCount = i + 1;
  118.       }
  119.       /* reset and process ALL (default:) */
  120.       else {
  121.         i = 0;
  122.         Entry = allEntries;
  123.       }
  124.  
  125.       for (; i < parseCount; i++, Entry++) {
  126.         char fileName[NAMELEN_PATH];
  127.  
  128.         __strncpy(fileName, destDir, NAMELEN_PATH - 1);
  129.         __strncat(fileName, Entry->name, NAMELEN_PATH - 1);
  130.  
  131.         switch (procOper) {
  132.           case OP_EXTRACT:{
  133.           HANDLE fileDst;
  134.  
  135.           mprintf(oper_extract, Entry->name, fileName);
  136.           CreatePath(fileName);
  137.  
  138.           if ((fileDst = __open(fileName, H_WRITE_BINARY)) > 0) {
  139.             struct rawdata *rawData;
  140.  
  141.             __lseek(pakFile, LittleLong(Entry->offset), SEEK_SET);
  142.             if ((rawData = GetRaw(pakFile, Entry->name, LittleLong(Entry->size)))) {
  143.               retval = PutRaw(fileDst, rawData);
  144.               rfree(rawData);
  145.               /* processName at this point */
  146.               if (recurse)
  147.             retval = processName(fileName, 0, 0, outType, 0, 0, procOper, script ? TRUE : FALSE, recurse);
  148.             }
  149.             else
  150.               eprintf(failed_memory, LittleLong(Entry->size), fileName);
  151.             __close(fileDst);
  152.           }
  153.           else
  154.             eprintf(failed_fileopen, fileName);
  155.         }
  156.         break;
  157.           case OP_DELETE:{
  158.           int diff, last;
  159.  
  160.           diff = LittleLong(Entry->size);
  161.           last = LittleLong(Entry->offset);
  162.  
  163.           mprintf(oper_delete, Entry->name, fileName);
  164.           /* delete from disk */
  165.           __lseek(pakFile, last, SEEK_SET);
  166.           if (CutOff(pakFile, diff, 0)) {
  167.             int content;
  168.  
  169.             /* correct header */
  170.             content = LittleLong(Header.size) / sizeof(struct packentry);
  171.             Header.size = LittleLong(LittleLong(Header.size) - sizeof(struct packentry));
  172.             Header.offset = LittleLong(LittleLong(Header.offset) - diff);
  173.  
  174.             /* delete from memlist */
  175.             __memcpy(Entry, Entry + 1, LittleLong(Header.size));
  176.             /* delete from loop */
  177.             parseCount--;
  178.             i--;
  179.             Entry--;
  180.  
  181.             /* correct all following offsets */
  182.             while (content--)
  183.               /* correct all, that come afterwards */
  184.               if (LittleLong(allEntries[content].offset) >= last)
  185.             allEntries[content].offset = LittleLong(LittleLong(Entry->offset) - diff);
  186.  
  187.             /* dump header */
  188.             __lseek(pakFile, 0, SEEK_SET);
  189.             __write(pakFile, &Header, sizeof(struct packheader));
  190.  
  191.             /* dump entries */
  192.             __lseek(pakFile, LittleLong(Header.offset), SEEK_SET);
  193.             __write(pakFile, allEntries, LittleLong(Header.size));
  194.             /* cut off removed entry */
  195.             retval = CutOff(pakFile, sizeof(struct packentry), 0);
  196.           }
  197.         }
  198.         break;
  199.           case OP_LIST:
  200.           case OP_DEFAULT:
  201.           default:{
  202.           mprintf("%54s %8d bytes (offset: %8x)\n", Entry->name, LittleLong(Entry->size), LittleLong(Entry->offset));
  203.           retval = TRUE;
  204.         }
  205.         break;
  206.         }
  207.  
  208.         if (script)
  209.           fprintf(script, "update %s as %s as %c\n", fileName, Entry->name, 'P');
  210.       }
  211.     }
  212.     break;
  213.     }
  214.     tfree(allEntries);
  215.   }
  216.   else
  217.     eprintf("no valid pakfile\n");
  218.  
  219.   return retval;
  220. }
  221.  
  222. bool AddPAK(struct palpic * inPic, struct rawdata * inData, char *pakName, operation procOper)
  223. {
  224.   char *procName;
  225.   HANDLE pakFile = __open(pakName, H_READWRITE_BINARY_OLD);
  226.   struct packheader Header;
  227.   struct packentry *Entry, *allEntries;
  228.   bool retval = FALSE;
  229.  
  230.   if (pakFile < 0)
  231.     pakFile = __open(pakName, H_READWRITE_BINARY_NEW);
  232.  
  233.   if (pakFile > 0) {
  234.     if (CheckPAK(pakFile, &Header, TRUE)) {
  235.       if (inPic) {
  236.     procName = inPic->name;
  237.     ReplaceExt(procName, "lmp");
  238.       }
  239.       else if (inData) {
  240.     procName = inData->name;
  241.       }
  242.  
  243.       /* we assume that the dir is at the end of the file!!!!! */
  244.       switch ((long int)(Entry = FindPAK(pakFile, procName, &Header, &allEntries))) {
  245.     case -1:
  246.       eprintf(failed_memory, LittleLong(Header.size) + sizeof(struct packentry), "packentries");
  247.       break;
  248.     case 0:
  249.       switch (procOper) {
  250.         case OP_REPLACE:
  251.           eprintf("no entry %s found to replace in pak %s\n", procName, pakName);
  252.           break;
  253.         case OP_UPDATE:
  254.           mprintf(oper_update, Entry->name[0] ? Entry->name : procName, pakName);
  255.           goto skip1;
  256.         case OP_ADD:
  257.         case OP_DEFAULT:
  258.         default:
  259.           mprintf(oper_add, Entry->name[0] ? Entry->name : procName, pakName);
  260.         skip1:
  261.           __lseek(pakFile, LittleLong(Header.offset), SEEK_SET);
  262.           /* seek to end of data */
  263.           Entry = allEntries + (LittleLong(Header.size) / sizeof(struct packentry));
  264.           Entry->offset = Header.offset;
  265.  
  266.           if (inData)
  267.         retval = PutRaw(pakFile, inData);
  268.           else if (inPic)
  269.         retval = PutLMP(pakFile, inPic);
  270.           else
  271.         eprintf("nothing to add\n");
  272.  
  273.           if (retval) {
  274.         Entry->size = LittleLong(__ltell(pakFile) - LittleLong(Header.offset));
  275.         __strncpy(Entry->name, procName, NAMELEN_PAK);
  276.         Header.size = LittleLong(LittleLong(Header.size) + sizeof(struct packentry));
  277.  
  278.         Header.offset = LittleLong(__ltell(pakFile));
  279.         /* write directory */
  280.         if (__write(pakFile, allEntries, LittleLong(Header.size)) == LittleLong(Header.size)) {
  281.           __lseek(pakFile, 0, SEEK_SET);
  282.           /* write header */
  283.           __write(pakFile, &Header, sizeof(struct packheader));
  284.         }
  285.         else
  286.           retval = FALSE;
  287.           }
  288.           else
  289.         eprintf(failed_filewritesize, procName, pakName);
  290.           break;
  291.       }
  292.       tfree(allEntries);
  293.       break;
  294.     default:
  295.       switch (procOper) {
  296.         case OP_REPLACE:
  297.           mprintf(oper_replace, Entry->name[0] ? Entry->name : procName, pakName);
  298.           goto skip2;
  299.         case OP_UPDATE:
  300.           mprintf(oper_update, Entry->name[0] ? Entry->name : procName, pakName);
  301.         skip2:{
  302.         int diff, last, newsize;
  303.  
  304.         newsize = (inData ? inData->size : ((inPic->width * inPic->height) + sizeof(struct lump)));
  305.  
  306.         diff = LittleLong(Entry->size) - newsize;
  307.         last = LittleLong(Entry->offset);
  308.  
  309.         __lseek(pakFile, last, SEEK_SET);
  310.         if (diff > 0) {
  311.           if (CutOff(pakFile, diff, 0))
  312.             retval = TRUE;
  313.         }
  314.         else if (diff < 0) {
  315.           if (PasteIn(pakFile, -diff, 0))
  316.             retval = TRUE;
  317.         }
  318.  
  319.         if (retval) {
  320.           int content;
  321.  
  322.           __lseek(pakFile, last, SEEK_SET);
  323.  
  324.           if (inData)
  325.             retval = PutRaw(pakFile, inData);
  326.           else if (inPic)
  327.             retval = PutLMP(pakFile, inPic);
  328.  
  329.           /* correct header */
  330.           content = LittleLong(Header.size) / sizeof(struct packentry);
  331.           Header.offset = LittleLong(LittleLong(Header.offset) - diff);
  332.  
  333.           /* correct all following offsets */
  334.           while (content--)
  335.             /* correct all, that come afterwards */
  336.             if (LittleLong(allEntries[content].offset) >= last)
  337.               allEntries[content].offset = LittleLong(LittleLong(Entry->offset) - diff);
  338.  
  339.           /* correct entry */
  340.           Entry->size = LittleLong(newsize);
  341.           Entry->offset = LittleLong(last);
  342.  
  343.           /* dump header */
  344.           __lseek(pakFile, 0, SEEK_SET);
  345.           __write(pakFile, &Header, sizeof(struct packheader));
  346.  
  347.           /* dump entries */
  348.           __lseek(pakFile, LittleLong(Header.offset), SEEK_SET);
  349.           __write(pakFile, &allEntries, LittleLong(Header.size));
  350.         }
  351.           }
  352.           break;
  353.         case OP_ADD:
  354.         case OP_DEFAULT:
  355.         default:
  356.           eprintf("old entry %s found in pak %s\n", procName, pakName);
  357.           break;
  358.       }
  359.       tfree(allEntries);
  360.       break;
  361.       }
  362.       __close(pakFile);
  363.     }
  364.     else
  365.       eprintf("no valid pakfile %s\n", pakName);
  366.   }
  367.   else
  368.     eprintf(failed_fileopen, pakName);
  369.  
  370.   return retval;
  371. }
  372.